package pruebasUnitarias;

import mapas.Mapa;
import mapas.Region;
import civilizacion.Civilizacion;
import unidades.Civil;
import unidades.Unidad;
import edificios.Casa;
import edificios.Edificio;
import edificios.EscuelaMilitar;
import edificios.Fabrica;
import excepcionesEdificios.ExcepNoEsEntrenador;
import excepcionesEdificios.ExcepNoEsGenerador;
import excepcionesGenerales.ExcepAtributoInvalido;
import excepcionesGenerales.ExcepImposibleEjecutar;
import excepcionesGenerales.ExcepNoEntrenable;
import excepcionesJugador.ExcepSinFondos;
import excepcionesRegion.ExcepRegionNoConquistada;
import jugadores.Jugador;
import junit.framework.TestCase;

public class PruebaCreacionUnidadesYEdificiosVarios extends TestCase {
	//atributos de la prueba
	private Civilizacion cvl;
	private Region reg;
	private Mapa mapa;
	private Jugador jugador;
	
	public PruebaCreacionUnidadesYEdificiosVarios(){
		//Inicializo los valores que son generales para todos
		mapa = new Mapa();
		cvl = new Civilizacion("C1",mapa);
		jugador = new Jugador("J1", cvl);
	}
	public void testCreacionCasaEnRegionNoConquistada(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente a la civilizacion
		cvl.setDinero(50);
		//Hago un construir casa de jugador
		try {
			jugador.construirCasa(reg);
		} catch (NullPointerException e) {
			fail("Deberia tirar error de imposible ejecutar");
		} catch (ExcepSinFondos e) {
			fail("Deberia tirar error de imposible ejecutar");
		} catch (ExcepImposibleEjecutar e) {
			return;
		}
		fail("La region no esta conquistada, no se tendria que poder consturir casa");
		mapa.QuitarRegion(reg);
	}
	public void testCreacionCasaEnRegionNoConquistadaConCivilPropio(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente a la civilizacion
		cvl.setDinero(50);
		//Agrego un civil propio en la region
		Unidad civil = new Civil(cvl, reg);
		reg.agregar(civil);
		//Hago un construir casa de jugador
		try{
		jugador.construirCasa(reg);
		} catch(Exception e){
			fail("Se tendria que poder construir una casa si hay un civil propio aunque no este conquistada la reg");
		}
		//Si paso es porque se pudo y esta bien
		mapa.QuitarRegion(reg);
	}
	public void testCreacionCasaSinFondos(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero insuficiente
		cvl.setDinero(0);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Intento construir una casa
		try {
				jugador.construirCasa(reg);
			} catch (NullPointerException e) {
				fail("Deberia tirar error de sin fondos");
			} catch (ExcepSinFondos e) {
				return;
			} catch (ExcepImposibleEjecutar e) {
				fail("Deberia tirar error de sin fondos");
			}
		fail("No hay suficiente recursos, no se tendria que poder crear la casa");
		mapa.QuitarRegion(reg);
	}
	public void testCreacionCasaEnCondFavorables(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente a la civilizacion
		cvl.setDinero(50);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Hago un construir casa de jugador
		try{
			jugador.construirCasa(reg);
		} catch(Exception e){
			fail("Se cumplen las condiciones, no tendria que fallar la creacion");
		}
		//Actualizo las colas y verifico que se cree a los 2 turnos
		reg.actualizarColasProduccion();
		//Me fijo si se creo
		assertEquals(reg.getCantidadElementosTotales(cvl),2); //Tendria que estar solo el civil y la casa del principio
		//Actualizo nuevamente
		reg.actualizarColasProduccion();
		//Me fijo si se creo
		assertEquals(reg.getCantidadElementosTotales(cvl), 3); //Tendria que haberse creado la nueva casa
		//Reviso el dinero
		assertEquals(cvl.getDinero(), 47); //La casa gasta 3 de oro
		mapa.QuitarRegion(reg);
	}
	public void testCreacionCivil(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente a la civilizacion
		cvl.setDinero(50);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Genero una unidad desde la casa
		try{
			jugador.generarUnidad(casa);
		} catch(Exception e){
			fail("Se cumplen las condiciones, no tendria que fallar la creacion");
		}
		//Actualizo las colas y verifico que se cree a los 2 turnos
		reg.actualizarColasProduccion();
		//Me fijo si se creo
		assertEquals(reg.getCantidadElementosTotales(cvl),2); //Tendria que estar solo el civil y la casa del principio
		//Actualizo nuevamente
		reg.actualizarColasProduccion();
		//Me fijo si se creo
		assertEquals(reg.getCantidadElementosTotales(cvl), 3); //Tendria que haberse creado el nuevo civil
		//Reviso el dinero
		assertEquals(cvl.getDinero(),50); //El civil es gratis, no se tendria que haber gastado dinero
		mapa.QuitarRegion(reg);
	}
	public void testCreacionCivilSinFondos(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero insuficiente
		cvl.setDinero(0);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Genero una unidad desde la casa
			try {
				jugador.generarUnidad(casa);
			} catch (ExcepSinFondos e) {
				fail("No hay fondos, sin embargo el civil es gratis");
			} catch (ExcepNoEsGenerador e) {
				fail("Se esta creando en un edificio generador de civiles");
			}
		mapa.QuitarRegion(reg);
	}
	public void testCreacionSoldados(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente
		cvl.setDinero(50);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Agrego una escuela
		Edificio escuela = new EscuelaMilitar(cvl, reg); /* No pruebo la construccion de una escuela 
		porque es similar a la de la casa */
		reg.agregar(escuela);
		//Entreno el civil en la escuela
			try {
				jugador.entrenarUnidadASoldado(civil, escuela);
			} catch (ExcepNoEntrenable e) {
				fail("El civil es entrenable");
			} catch (ExcepSinFondos e) {
				fail("La civilizacion tiene el dinero suficiente");
			} catch (ExcepNoEsEntrenador e) {
				fail("El edificio puede entrenar");
			}
		//Me fijo si se crea en el 3er turno
		for (int cont = 0; cont<=2; cont++){
			reg.actualizarColasProduccion();
			if (cont != 2)
				assertEquals(reg.getUnidades().getCantidadElementos(),0); //No esta el civil porque esta en la escuela
			else
				assertEquals(reg.getUnidades().getCantidadElementos(),1); //Aparece el soldado
		}
		//reviso el dinero
		assertEquals(cvl.getDinero(),48);
		mapa.QuitarRegion(reg);
	}
	/**
	 *La siguiente prueba es muy parecida a la de creacion de casas,
	 *asi que se hara de forma simple
	 */
	public void testCreacionFabrica(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente a la civilizacion
		cvl.setDinero(50);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Hago un construir fabrica de jugador
			try {
				jugador.construirFabrica(reg);
			} catch (NullPointerException e) {
				fail("Se cumplen las condiciones, se tendria que poder entrenar");
			} catch (ExcepAtributoInvalido e) {
				fail("Se cumplen las condiciones, se tendria que poder entrenar");
			} catch (ExcepSinFondos e) {
				fail("Se dispone del dinero suficiente para la creacion");
			} catch (ExcepRegionNoConquistada e) {
				fail("La region deberia estar conquistada");
			}
		//Actualizo las colas y verifico que se cree a los 4 turnos
		for (int cont = 0; cont<=3; cont++){
			reg.actualizarColasProduccion();
			if (cont !=3)
				assertEquals(reg.getEdificios().getCantidadElementos(),1); //Esta solo la casa
			else
				assertEquals(reg.getEdificios().getCantidadElementos(),2); //Aparece la fabrica
		}
		//Reviso el dinero
		assertEquals(cvl.getDinero(), 30); //La fabrica gasta 20 de oro
		mapa.QuitarRegion(reg);
	}
	/**
	 *La siguiente prueba es muy parecida a la de creacion de civiles,
	 *asi que se hara de forma simple
	 */
	public void testCreacionCamion(){
		reg = new Region("R1", 2);
		mapa.AgregarRegion(reg);
		//Agrego dinero suficiente a la civilizacion
		cvl.setDinero(50);
		//Conquisto la region agregando un civil y una casa
		Unidad civil = new Civil(cvl, reg);
		Edificio casa = new Casa(cvl, reg);
		reg.agregar(civil);
		reg.agregar(casa);
		//Creo una fabrica
		Edificio fabrica = new Fabrica(cvl,reg);
		reg.agregar(fabrica);
		//Genero una unidad de la fabrica
			try {
				jugador.generarUnidad(fabrica);
			} catch (ExcepSinFondos e) {
				fail("Hay fondos suficientes");
			} catch (ExcepNoEsGenerador e) {
				fail("El edificio genera unidades");
			}
		//Me fijo si se crea en el 5to turno
		for (int cont = 0; cont<=4; cont++){
			reg.actualizarColasProduccion();
			if (cont != 4)
				assertEquals(reg.getUnidades().getCantidadElementos(),1); //Hay solo un civil
			else
				assertEquals(reg.getUnidades().getCantidadElementos(),2); //Aparece el camion
		}
		//reviso el dinero
		assertEquals(cvl.getDinero(),44); //el camion vale 6
		mapa.QuitarRegion(reg);
	}
}

